/*
Copyright (c) [2019年5月1日] [吴超]
[MBT_Studio] is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:
		 http://license.coscl.org.cn/MulanPSL2
THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
*/
#include "stdafx.h"
#include "节点视口工作区.h"

#include "框架/工作区/节点视口/节点构建.h"
#include "B_场景管理/节点管理.h"


#include "框架/工作区/节点视口/ui堆栈节点视口.h"
#include "框架/工作区/节点视口/ui节点创建菜单.h"


static std::set<C_工作区页面*> g_节点视口页面;



static bool on_文件处理回调(C_Widget* self, const std::vector<std::string>& name, E_对话框类型 方式) {
	for (auto& e : name) {
		auto 后缀 = f_file_get文件名后缀(e);
		if (后缀 == "png" || 后缀 == "jpg" || 后缀 == "tga") {

		}
	}
	return true;
}

static void f_PropUpdate_返回上一级节点树(S_Props& prop) {
}

static void on_节点树列表_项改变(S_Props& prop, S_MapPtr& ptrItem, int32 操作类型) {
	C_节点视口状态条* bar = static_cast<C_节点视口状态条*>(prop.m_UI->m_部件->m_父部件->m_父部件);


	switch (操作类型) {
		case E_Prop_MapPtr_项事件类型::e_项删除:
			ptrItem.m_PtrItem.erase(ptrItem.m_PtrItem.begin() + ptrItem.m_当前项);
			break;

		case E_Prop_MapPtr_项事件类型::e_项名称改变: {
			auto& e = ptrItem.m_PtrItem[ptrItem.m_当前项];
			((C_节点树*)e.m_Ptr)->g_树名称分配.f_Move(e.m_Str);
			e.m_Str = ((C_节点树*)e.m_Ptr)->g_树名称分配.f_Gen(e.m_Str);
			//ptrItem.m_PtrItem[ptrItem.m_当前项].m_Str;
			break;
		}

		case E_Prop_MapPtr_项事件类型::e_项添加: {
			S_MapPtrItem item;
			C_节点树* tree = f_node_Create节点树(true);
		
			bar->m_View->f_nodeTree_绑定(tree);
			break;
		}

		default: {
			uint32 offset = ptrItem.m_当前项;
			S_MapPtrItem& item = ptrItem.m_PtrItem[offset];

			bar->m_View->f_nodeTree_绑定((C_节点树*)item.m_Ptr);
			break;
		}
	}

}

void f_工作区页面_物体节点工作区初始化(S_UI渲染环境& ctx) {
	//C_节点视口::g物体节点创建菜单 = f_init物体节点创建菜单(ctx);
	//C_节点视口::g函数节点创建菜单 = f_init函数节点创建菜单(ctx);
	//C_节点视口::g多边形节点创建菜单 = f_init多边形节点创建菜单(ctx);
	//C_节点视口::g材质节点创建菜单 = f_init材质节点创建菜单(ctx);
	//C_节点视口::g着色器节点创建菜单 = f_init着色器节点创建菜单(ctx);
	//C_节点视口::g几何着色节点创建菜单 = f_init几何着色器节点创建菜单(ctx);
	//C_节点视口::g并行节点创建菜单 = f_init并行节点创建菜单(ctx);

	C_节点视口::g节点层级切换面板 = f_ui_创建扩展弹出菜单(ctx, E_方向::e_纵向, true);
	
	f_init_物体节点创建_绑定视口回调(f_NodeView_其他工作区添加面板到视口, f_NodeView_添加节点面板到视口);

	f_扩展节点_构建函数初始化(ctx, f_NodeView_其他工作区添加面板到视口);
	//f_init节点视口(ctx.m_Ctx);
}

static bool on_节点视口打开关闭(C_Widget* self, bool show) {
	C_工作区页面* 工作区 = dynamic_cast<C_工作区页面*>(self);

	auto* 节点视口 = 工作区->mui_视口页面->f_get子组件(0);
	auto* 搭线面板 = 工作区->mui_视口页面->f_get子组件(1);

	if (show) {
		S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_属性栏);
		S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_状态条);
	}
	else {
		S_框架::m_工作区属性面板渲染层ID分配.f_移除渲染层组件(工作区->mui_属性栏);
		S_框架::m_工作区属性面板渲染层ID分配.f_移除渲染层组件(工作区->mui_状态条);
	}
	
	return false;
}


C_工作区页面* f_工作区_创建节点视口(S_UI渲染环境& ctx) {
	auto 状态条 = new C_节点视口状态条(ctx);
	
	auto& p = f_prop_映射引用2D(状态条->m_节点树容器);
	p.mf_元素选择 = on_项选择_切换节点树;

	C_节点树* t = nullptr;
	if (p.m_PtrItem[0]->size()) {
		t = (C_节点树*)p.m_PtrItem[DEF_节点树容器槽偏移_物体]->back().m_Ptr;
	}
	else {
		t = f_node_Create节点树(true, u"默认节点树");
	}


	auto* 滚动窗口 = f_NodeView_创建节点视口(ctx, t);

	C_节点视口* nodeview = dynamic_cast<C_节点视口*>(滚动窗口->m_子组件[0]);
	nodeview->m_节点树容器 = 状态条->m_节点树容器;
	状态条->m_View = nodeview;


	C_工作区页面* 工作区 = new C_工作区页面(E_工作区类型::e_节点视口, ctx, E_方向::e_横向, 滚动窗口, 状态条, nodeview->m_属性栏);
	工作区->mf_打开关闭 = on_节点视口打开关闭;

	f_节点工作区_重构状态条(工作区->mui_状态条);


	S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_属性栏);
	S_框架::m_工作区属性面板渲染层ID分配.f_置组件渲染层(工作区->mui_状态条);
	g_节点视口页面.insert(工作区);
    return 工作区;
}











C_工作区页面* f_工作区_create材质节点视口(S_UI渲染环境& ctx) {
	auto 状态条 = new C_节点视口状态条(ctx);

	状态条->m_节点树容器 = f_alloc_StrIndexProp(S_框架::g_材质节点树, u"");
	
	auto& p = f_prop_映射引用2D(状态条->m_节点树容器);
	p.mf_元素选择 = on_项选择_切换节点树;


	C_节点树* t = nullptr;
	if (p.m_PtrItem[0]->size()) {
		t = (C_节点树*)p.m_PtrItem[0]->back().m_Ptr;
	}
	else {
		t = f_node_Create节点树(true, u"默认节点树");
	}

	auto* 滚动窗口 = f_NodeView_创建节点视口(ctx, t);
	
	C_节点视口* nodeview = dynamic_cast<C_节点视口*>(f_ui_get滚动框视口(滚动窗口));
	状态条->m_View = nodeview;
	nodeview->m_节点树容器 = 状态条->m_节点树容器;

	//nodeview->m_节点菜单 = C_节点视口::g物体节点创建菜单;
	//nodeview->m_节点删除菜单 = f_通用菜单_节点删除菜单(ctx, on_NodeView_删除节点菜单项);
	//nodeview->mf_以节点构建节点 = f_节点构建_从节点构建节点;
	//nodeview->mf_节点重构回调 = f_节点构建_重构;
	//nodeview->mf_名称构建节点面板 = f_节点构建_用名称构建节点面板;
	//g_节点视口s.push_back(nodeview);


	C_工作区页面* 工作区 = new C_工作区页面(E_工作区类型::e_节点视口, ctx, E_方向::e_横向, 滚动窗口, 状态条, nodeview->m_属性栏);

	f_节点工作区_重构状态条(工作区->mui_状态条);
	return 工作区;
}


C_Widget* f_工作区_get节点视口(uint32 id) {
	//if (g_节点视口s.size() > id) {
	//	return g_节点视口s[id];
	//}
	return nullptr;
}






static void on_3D视口场景物体显示方式(S_Props& prop) {

}

static void on_节点树排列方向切换(S_Props& prop) {

}

static void propUpdate_节点树类型切换视口(S_Props& prop) {
	f_节点视口工作区_更新所有视口节点树类型();

	//f_widget_更新渲染层(prop.m_UI->m_部件);
	f_工作区_联动更新(E_工作区类型::e_属性面板, E_工作区操作类型::e_修改节点名称);
}




void f_节点工作区_重构状态条(C_状态条* 状态条) {
	C_节点视口状态条* bar = static_cast<C_节点视口状态条*>(状态条);
	

	std::vector<S_Props> props;
	S_Props	prop;
	prop = f_alloc_OpsProp(f_PropUpdate_返回上一级节点树, u"返回上一级");
	props.push_back(prop);
	
	props.push_back(f_alloc_NoneProp());
	props.push_back(bar->m_节点树类型);
	bar->m_节点树类型.m_UI->m_Update = propUpdate_节点树类型切换视口;

	switch (f_prop_enum(bar->m_节点树类型)) {
		case 0: {
			if (S_框架::g_拾取物体.size()) {
				//prop = f_alloc_Object(&S_框架::g_物体节点, (*S_框架::g_拾取物体.begin())->m_网格修改器[0]);
				auto& item = *f_prop_ObjectMap(bar->m_当前物体节点树);
				if ((*S_框架::g_拾取物体.begin())->m_扩展属性[0]) {
					f_prop_ObjectMapSelect(bar->m_当前物体节点树, (*S_框架::g_拾取物体.begin())->m_扩展属性[0]->m_Name);
				}
				props.push_back(bar->m_当前物体节点树);
			}
			break;
		}
		case 1: {
			//auto& item = *f_prop_ObjectMap(bar->m_当前场景节点树);
			//f_prop_ObjectArraySelect(bar->m_当前场景节点树, item.当前选项);
			props.push_back(bar->m_当前场景节点树);
			break;
		}
		default:
			break;
	}
	
	
	//props.push_back(bar->m_节点树容器);
	props.push_back(f_alloc_NoneProp());
	prop = f_alloc_EnumProp(nullptr,
		{ {u"显示所有", u"布尔并"}, {u"独显选择", u"布尔阳"}, {u"隐藏未选择", u"布尔阴"} },
		u"场景物体显示方式",
		0,
		on_3D视口场景物体显示方式);
	//props.push_back(prop);

	//props.push_back(f_alloc_NoneProp());
	prop = f_alloc_EnumProp(nullptr, { 
		{u"横向排列", u"横向排列"}, 
		{u"纵向排列", u"纵向排列"},
	
	},
		u"排列方向",
		0,
		on_节点树排列方向切换);

	//f_prop_MapPrt(bar->m_节点树容器).m_当前项;

	//props.push_back(prop);

	状态条->f_构建属性部件(props, 状态条);

}





E_事件是否传递 f_节点工作区_拷贝节点(C_Widget* self, uint8 状态) {
	
	return E_事件是否传递();
}







C_工作区页面* f_工作区_create堆栈节点视口(S_UI渲染环境& ctx) {
	C_Widget* page = f_工作区页面_创建堆栈节点视口(ctx);

	C_工作区页面* 工作区 = new C_工作区页面(E_工作区类型::e_节点视口, ctx, E_方向::e_横向, page);
	//f_节点工作区_重构状态条(工作区->mui_状态条);
	return 工作区;
}

void f_节点视口工作区_销毁() {
	for (auto& e : g_节点视口页面) {
		on_节点视口打开关闭(e, false);
	}
	g_节点视口页面.clear();
}


void f_节点视口工作区_更新所有视口节点树类型() {
	for (auto& 工作区 : g_节点视口页面) {
		if (!工作区->m_被裁剪) {
			f_widget_更新绘制(工作区);
		}
	}
}

void f_节点视口工作区_更新当前引用节点() {
	for (auto& 工作区 : g_节点视口页面) {
		if (!工作区->m_被裁剪) f_节点工作区_重构状态条(工作区->mui_状态条);
		break;
	}
}

void f_节点工作区页面_联动更新(E_工作区类型 来源工作区类型, E_工作区操作类型 操作类型) {
	switch (操作类型) {
		case e_创建节点:
		case e_删除节点:
			break;

		case e_创建物体:
		case e_删除物体:
		case e_拾取物体: {
			for (auto& 工作区 : g_节点视口页面) {
				f_节点工作区_重构状态条(工作区->mui_状态条);
			}
			break;
		}

		case E_工作区操作类型::e_变换物体: {
			
			break;
		}
		default:
			break;
	}
}



void f_物体节点工作区_保存工作区状态(FILE* f, C_工作区页面* 页面) {
	C_节点视口状态条* bar = static_cast<C_节点视口状态条*>(页面->mui_状态条);
	auto& 映射项 = f_prop_映射引用2D(bar->m_节点树容器);


	auto 文件块 = f_文件块_创建(E_节点工程文件块类型::e_工程文件块_工作区页面布局, S_引擎配置::g_文件版本号);
	S_UI8Array* 块 = (S_UI8Array*)f_core_array_new(0, sizeof(uint8));

	f_文件块_写数据块(块, 映射项.m_当前项);
	f_文件块_写数据块(块, *bar->m_View->m_扩展视口属性);

	f_file_保存文件块(f, 文件块, 块);
	//fwrite(&映射项.m_当前项, sizeof(映射项.m_当前项), 1, f);
	//fwrite(bar->m_View->m_扩展视口属性, sizeof(S_View属性), 1, f);
}

void f_物体节点工作区_加载工作区状态(FILE* f, C_工作区页面* 页面) {
	C_节点视口状态条* bar = static_cast<C_节点视口状态条*>(页面->mui_状态条);

	auto& 映射项 = f_prop_映射引用2D(bar->m_节点树容器);

	if (S_引擎配置::g_当前加载文件版本号 > S_引擎配置::g_低版本号_8) {
		S_文件块 文件块 = f_file_读取文件块(f);
		if (文件块.m_块类型 == E_节点工程文件块类型::e_工程文件块_工作区页面布局) {
			const uint8* 下一次读取数据指针 = 文件块.m_data;

			if (f_file_版本对比(文件块, S_引擎配置::g_低版本号_8, S_引擎配置::g_文件版本号)) {
				
				下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, 映射项.m_当前项);
				S_View属性 View属性;
				下一次读取数据指针 = f_文件块_读数据块(下一次读取数据指针, View属性);

				(*bar->m_View->m_扩展视口属性) = View属性;
			}
		}
		free(文件块.m_data);
	}
	else {
		auto& 映射项 = f_prop_映射引用2D(bar->m_节点树容器);
		//S_MapPtr& 映射项 = f_prop_MapPrt(bar->m_节点树容器);
		fread(&映射项.m_当前项, sizeof(映射项.m_当前项), 1, f);
		fread(bar->m_View->m_扩展视口属性, sizeof(S_View属性), 1, f);
	}

	bar->m_View->f_nodeTree_绑定((C_节点树*)((*映射项.m_PtrItem[映射项.m_当前项.x])[映射项.m_当前项.y].m_Ptr));
}










//static void on_节点树列表_编辑名称(S_Props& prop) {
//	auto& p = f_prop_MapPrt(prop);
//}




//static void on_节点树列表_重构节点视口内节点(S_Props& prop) {
//	auto& p = f_prop_MapPrt(prop);
//}

/*void on_工作区联动更新(E_工作区类型 主工作区, C_工作区页面* 工作区) {
//更新指定节点
//auto node = f_global_get激活节点();
C_节点视口状态条* bar = static_cast<C_节点视口状态条*>(工作区->m_状态条);
f_NodeView_更新节点(bar->m_View);
}*/



